`timescale 1ns / 1ns


////////////////////////////////////////////////////
// Comments for WR_interface.v //
////////////////////////////////////////////////////

// i_rst is reset signal for the module with positive voltage.
// i_clk is 48M, which is below 50M, and the clock 48M can seperate from 100M, 
// One-third of 48M is 16M, which is the work clock requirement of SJA1000T.

// This module implements the steps to write data. Through this module, 
// corresponding data can be written to the internal registers of the SJA1000T, 
// thereby enabling the configuration of the SJA1000T and the communication of writing data on the CAN bus.

// o_WRflag indicates that it is currently in the write interface state. 
	// When the signal flag is 1, it indicates that it is in the write interface state, 
	// and when it is 0, it indicates that it is not in the write interface state.

// crucial interface：
	// wr_trig,  [7:0] WR_data, [7:0] WR_addr. 
// wr_trig indicates that it's necessary to start wr_interface state machine for writing the [7:0] WR_data at [7:0] WR_addr.
// o_WR_finish indicates that the last [7:0] WR_data has been written at [7:0] WR_addr.

// Relevent signal of WRinterface: 
	// o_chip_oe, 
	// [7:0] o_sja1000_data_wr, 
	// o_sja1000_wr_n,
	// o_sja1000_ale,
	// o_sja1000_cs_n



//FIRST: the input signal buffer two clocks for removing metastability.

	// wr_trig1；
	// wr_trig_r. stable with two clocks buffer.
	// and when the wr_trig_r take effct, 
	// the input information [7:0] WR_data, [7:0] WR_addr are latched in [7:0] WRdat, [7:0] WRadd at wr_trig.
	// which insures that the valid information indeed be latched correctly and put into application after latch procedure.

	// [7:0] WRdat, [7:0] WRadd be cleared at WR_finish.


// To avoid the work clock 48M is too soon to WR interface.v, we seperate the 48M with quarter frequency 24M.

// When DIR is 1, [7:0] CAN1_AD are ouput;
// Similarly, when When DIR is 0, [7:0] CAN1_AD are input. 

// when chip_oe is 1, [7:0] CAN1_AD are ouput;
// Similarly, when When chip_oe is 0, [7:0] CAN1_AD are input. 






/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// input i_rst, //高电平复位
// input i_clk, //工作时钟48M

// output wire o_WRflag,  //表示正处于写状态。

// input wr_trig, //写触发信号
// input [7:0] WR_addr, //写的地址
// input [7:0] WR_data, //写的数据

// output wire o_WR_finish, //表示完成了此状态的写。

// output wire o_chip_oe, //软件层面对应的CAN_AD8bits数据三态门实际处理
// output wire [7:0] o_sja1000_data_wr, //要拿去写的数据
// output wire o_sja1000_wr_n, //写信号线_低有效
// output wire o_sja1000_ale, //标识当前数据位代表地址信号的信号
// output wire o_sja1000_cs_n //片选信号线_低有效
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////






module WR_interface(

input i_rst,
input i_clk,

output wire o_WRflag,

input wr_trig,
input [7:0] WR_addr,
input [7:0] WR_data,

output wire o_WR_finish,

output wire o_chip_oe,
output wire [7:0] o_sja1000_data_wr,
output wire o_sja1000_ale,
output wire o_sja1000_cs_n,
output wire o_sja1000_wr_n

);









 localparam IDLER =	16'b0000_0000_0000_0000;
 localparam S1R =		16'b0000_0000_0000_0001;
 localparam S2R =		16'b0000_0000_0000_0010;
 localparam S3R =		16'b0000_0000_0000_0100;
 localparam S4R =		16'b0000_0000_0000_1000;
 localparam S5R =		16'b0000_0000_0001_0000;
 localparam S6R =		16'b0000_0000_0010_0000;
 localparam S7R =		16'b0000_0000_0100_0000;
 localparam S8R =		16'b0000_0000_1000_0000;
 localparam S9R =		16'b0000_0001_0000_0000;
 localparam S10R =	16'b0000_0010_0000_0000;
 localparam S11R =	16'b0000_0100_0000_0000;
 localparam S12R =	16'b0000_1000_0000_0000;
 localparam S13R =	16'b0001_0000_0000_0000;
 localparam S14R =	16'b0010_0000_0000_0000;
 localparam S15R =	16'b0100_0000_0000_0000;
 localparam S16R =	16'b1000_0000_0000_0000;









	reg wr_trig0, wr_trig1;
	always@(posedge i_clk) 
	begin

		if(i_rst) 
			begin 
				wr_trig1 <= 1'd0;
				wr_trig0 <= 1'd0; 
			end 
			
		else 
			begin 
				wr_trig1 <= wr_trig0; 
				wr_trig0 <= wr_trig; 
			end 

	end

wire wr_trig_r;
assign wr_trig_r = (~wr_trig0)&& wr_trig1;

reg WRflag,WR_finish;
reg [7:0] WRdat, WRadd;

always@(posedge i_clk) 
begin

	if(i_rst) 
		begin 
			WRdat <= 8'd0; 
			WRadd <= 8'd0; 
		end 
		
	else if(WR_finish) 
		begin 
			WRdat <= 8'd0; 
			WRadd <= 8'd0; 
		end 
		
	else if(wr_trig) 
		begin 
			WRdat <= WR_data; 
			WRadd <= WR_addr; 
		end
		
end 








reg chip_oe;
reg sja1000_ale;
reg sja1000_cs_n;
reg sja1000_wr_n;
reg [7:0] sja1000_data_wr;


reg [15:0] st;
(* KEEP="TRUE" *)(* S="YES" *) reg [15:0] st_temp;

always @(posedge i_clk) 
begin 

	if(i_rst)
		begin 
			st_temp <= 16'd0; 
		end
		
	else 
		begin 
			st_temp <= st; 
		end
		
end


always@(posedge i_clk) 
begin

	if(i_rst) 
		begin 
			chip_oe <= 1'b0; 
			sja1000_ale <= 1'b0; 
			sja1000_cs_n <= 1'b1;
			sja1000_wr_n <= 1'b1;
			sja1000_data_wr <= 8'h00; 
			WRflag <= 1'b0;
			WR_finish<= 1'b0; 
			st<=IDLER; 
		end
		
	else 
		begin
	
			case(st)
			
				IDLER: 
					begin
						chip_oe <= 1'b0; 
						sja1000_data_wr <= 8'h00; 
						sja1000_ale <= 1'b0; 
						sja1000_wr_n <= 1'b1; 
						sja1000_cs_n <= 1'b1;
						WRflag <= 1'b0; 
						WR_finish<= 1'b0; 
						
							if(wr_trig_r) 
								begin 
									st<=S1R; 
								end
								
					end
					
				S1R: 
					begin 
					
								WRflag <= 1'b1;
								st<=S2R;
					
					end
				
				S2R: 
					begin
 
								chip_oe <= 1'b1;
								st<=S3R;

					end 
				
				S3R:
					begin

								sja1000_data_wr <= WRadd; 
								st<=S4R; 
					
					end 
				
				S4R: 
					begin

								sja1000_ale <= 1'b1;
								st<=S5R; 

					end 
				
				S5R: 
					begin

								st<=S6R; 

					end 
				
				S6R: 
					begin 
					
								sja1000_ale <= 1'b0;
								st<=S7R;
					end 
				
				S7R: 
					begin

								sja1000_data_wr <=WRdat; 
								st<=S8R; 
					
					end 
				
				S8R: 
					begin
 
								sja1000_cs_n <= 1'b0;
								st<=S9R; 
					
					end 
				
				S9R: 
					begin

								sja1000_wr_n <= 1'b0;
								st<=S10R; 
					
					end 
				
				S10R: 
					begin

								st<=S11R;

					end 
				
				S11R: 
					begin

								sja1000_wr_n <= 1'b1; 
								st<=S12R;
					
					end 
				
				S12R: 
					begin

								sja1000_cs_n <= 1'b1; 
								st<=S13R; 
					
					end 
				
				S13R: 
					begin 
					
								st<=S14R;
					
					end 
				
				S14R: 
					begin

								st<=S15R;
					
					end 
				
				S15R: 
					begin 
					
								chip_oe <= 1'b0; 
								WR_finish<= 1'b1; 
								st<=S16R; 

					end 
				
				S16R: 
					begin 
					
								WRflag <= 1'b0; 
								WR_finish<= 1'b0;
								st <= IDLER; 
					
					end
				
				default:
					begin
						st<=IDLER;
					end
					
			endcase 
		
		end 
	
end





assign o_WRflag = WRflag;
assign o_WR_finish = WR_finish;





assign o_chip_oe =  WRflag? chip_oe:1'd0;
assign o_sja1000_ale = WRflag? sja1000_ale:1'd0;
assign o_sja1000_cs_n = WRflag? sja1000_cs_n:1'd1;
assign o_sja1000_wr_n = WRflag? sja1000_wr_n:1'd1;
assign o_sja1000_data_wr = WRflag? sja1000_data_wr: 8'd0;





endmodule

